package panel;

import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import util.*;

import javax.swing.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;

public class MVPFilesPanel extends JPanel {
    private Project project;
    JTextField packageName, name, username, description;
    JRadioButton activityJB, fragmentJB, useDataBinding, notUseDataBinding;
    /*当前右键选中包名 com.aa.aa*/
    private String packagebase = "";
    //android package
    private String applicationId = "";
    //右键路径
    private String rightClickPath;
    private String contractPath;
    private String viewPath;
    private String presenterPath;
    private String modelPath;
    private String layoutPath;
    private String contractName;
    private String viewName;
    private String presenterName;
    private String modelName;
    private String layoutName;

    private AnActionEvent event;
    private CloseListener closeListener;

    public MVPFilesPanel(AnActionEvent event, CloseListener closeListener) {
        this.event = event;
        this.closeListener = closeListener;
        project = event.getData(PlatformDataKeys.PROJECT);
        packagebase = PathUtil.readPackageName(event);
        rightClickPath = PathUtil.getFileSavePath(event) + "/";
        applicationId = PathUtil.readModuleApplicationId(rightClickPath);
        initView();
    }

    private void initView() {
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        JPanel panelname = new JPanel();// /定义一个面板
        panelname.setLayout(new GridLayout(2, 2));
        panelname.setBorder(BorderFactory.createTitledBorder("命名"));

        packageName = new JTextField();
        packageName.setText("目录名称");
        panelname.add(packageName);

        name = new JTextField();
        name.setText("组件名字");
        panelname.add(name);

        description = new JTextField();
        description.setText("组件描述(注释)");
        panelname.add(description);

        username = new JTextField();
        username.setText("作者");
        panelname.add(username);

        add(panelname);

        activityJB = new JRadioButton("Activity");// 定义一个单选按钮
        fragmentJB = new JRadioButton("Fragment");// 定义一个单选按钮

        activityJB.setSelected(true);

        JPanel panel = new JPanel();// /定义一个面板
        panel.setBorder(BorderFactory.createTitledBorder("选择生成代码的类型"));// 定义一个面板的边框显示条
        panel.setLayout(new GridLayout(1, 2));// 定义排版，一行三列
        panel.add(activityJB);// 加入组件
        panel.add(fragmentJB);// 加入组件

        ButtonGroup group = new ButtonGroup();
        group.add(activityJB);
        group.add(fragmentJB);
        add(panel);// 加入面板

        notUseDataBinding = new JRadioButton("否");
        useDataBinding = new JRadioButton("是");
        notUseDataBinding.setSelected(true);
        JPanel panelDataBinding = new JPanel();
        panelDataBinding.setBorder(BorderFactory.createTitledBorder("是否使用dataBinding"));
        panelDataBinding.setLayout(new GridLayout(1, 2));
        panelDataBinding.add(notUseDataBinding);
        panelDataBinding.add(useDataBinding);

        ButtonGroup groupDataBinding = new ButtonGroup();
        groupDataBinding.add(notUseDataBinding);
        groupDataBinding.add(useDataBinding);
        add(panelDataBinding);

        JPanel menu = new JPanel();
        menu.setLayout(new FlowLayout());

        Button cancle = new Button();
        cancle.setLabel("取消");
        cancle.addActionListener(actionListener);

        Button ok = new Button();
        ok.setLabel("确定");
        ok.addActionListener(actionListener);
        menu.add(cancle);
        menu.add(ok);
        add(menu);
    }

    private ActionListener actionListener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getActionCommand().equals("取消")) {
                closeListener.onClose();
            } else {
                closeListener.onClose();
                clickCreateFile();
            }
        }
    };

    private void clickCreateFile() {
        // 检测是否有同名文件，有的话直接报错
        CheckFileExistResult checkFileExistResult = checkFileExit();
        if (checkFileExistResult.isExist()) {
            Messages.showErrorDialog(project, checkFileExistResult.getMsg(), "提示");
        } else {
            createFiles(CodeType.Contract);
            if (activityJB.isSelected()) {
                createFiles(CodeType.Activity);
            }
            if (fragmentJB.isSelected()) {
                createFiles(CodeType.Fragment);
            }
            createFiles(CodeType.Model);
            createFiles(CodeType.Presenter);
            // 自动刷新目录
            refreshProject(event);
            Messages.showInfoMessage(project, "代码生成成功", "提示");
        }
    }


    /**
     * 刷新项目
     */
    private void refreshProject(AnActionEvent e) {
        e.getProject().getBaseDir().refresh(false, true);
    }

    /**
     * 创建文件
     */
    private void createFiles(CodeType codeType) {
        String filename = ""; //模板文件名
        String content = ""; //模板文件内容

        switch (codeType) {
            case Contract:
                filename = "TemplateContract.txt";
                content = ReadFile(Constants.TemplateContract, filename);
                // 1.通用流程,处理顶部注释
                content = dealFileTitle(content);
                content = dealContract(content);
                FileUtils.reWriteFile(content, contractPath, contractName);
                break;
            case Activity:
                filename = useDataBinding.isSelected() ? "TemplateActivityDataBinding.txt" : "TemplateActivity.txt";
                content = useDataBinding.isSelected() ? ReadFile(Constants.TemplateActivityDataBinding, filename) : ReadFile(Constants.TemplateActivity, filename);
                content = dealFileTitle(content);
                content = dealActivity(content);
                FileUtils.reWriteFile(content, viewPath, viewName);
                // 新建layout文件
                String layoutContent = dealLayout(ReadFile(Constants.TemplateLayout, "TemplateLayout.txt"));
                FileUtils.reWriteFile(layoutContent, layoutPath, layoutName + ".xml");
                //往xml中写入注册Activity
                writeActivityToAndroidManifest(packagebase + "." + packageName.getText() + ".view." + name.getText() + "Activity");
                break;
            case Presenter:
                filename = "TemplatePresenter.txt";
                content = ReadFile(Constants.TemplatePresenter, filename);
                content = dealFileTitle(content);
                content = dealPresenter(content);
                FileUtils.reWriteFile(content, presenterPath, presenterName);
                break;
            case Model:
                filename = "TemplateModel.txt";
                content = ReadFile(Constants.TemplateModel, filename);
                content = dealFileTitle(content);
                content = dealModel(content);
                FileUtils.reWriteFile(content, modelPath, modelName);
                break;
            case Fragment:
                filename = "TemplateFragment.txt";
                content = ReadFile(Constants.TemplateFragment, filename);
                content = dealFileTitle(content);
                content = dealFragment(content);
                FileUtils.reWriteFile(content, viewPath, viewName);
                // 新建layout文件
                String layoutFragment = dealLayout(ReadFile(Constants.TemplateFragmentLayout, "TemplateFragmentLayout.txt"));
                FileUtils.reWriteFile(layoutFragment, layoutPath, layoutName + ".xml");
                break;
            default:
                break;
        }
    }

    /**
     * 处理Contract
     *
     * @param content
     * @return
     */
    private String dealContract(String content) {
        content = content.replace("$name", name.getText());
        content = content.replace("$packagename", packagebase + "." + packageName.getText() + ".contract");
        return content;
    }

    /**
     * manifest 注册Activity
     *
     * @param content
     */
    private void writeActivityToAndroidManifest(String content) {
        //manifest路径
        int begin = rightClickPath.indexOf("/src/main/java");
        String manifestPath = rightClickPath.substring(0, begin) + "/src/main/AndroidManifest.xml";
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(new InputSource(new FileInputStream(manifestPath)));
            Element newEle = doc.createElement("activity");
            newEle.setAttribute("android:name", content);
            newEle.setAttribute("android:exported", "false");
            Node node = doc.getElementsByTagName("application").item(0);
            node.appendChild(newEle);
            Source sour = new DOMSource(doc);
            Result result = new StreamResult(new FileOutputStream(manifestPath));
            FileUtils.write(sour, result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理presenter
     *
     * @return
     */
    private String dealPresenter(String content) {
        content = content.replace("$name", name.getText());
        content = content.replace("$packagename", packagebase + "." + packageName.getText() + ".presenter");
        content = content.replace("$packagebase", packagebase + "." + packageName.getText());
        return content;
    }

    /**
     * 处理layout
     *
     * @param content
     * @return
     */
    private String dealLayout(String content) {
        content = content.replace("$name", name.getText());
        content = content.replace("$titleid", StringUtil.upperCharToUnderLine("title" + name.getText()));
        content = content.replace("$description", description.getText());
        content = content.replace("$packagename", packagebase + "." + packageName.getText());
        return content;
    }

    /**
     * 处理activity
     *
     * @param content
     * @return
     */
    private String dealActivity(String content) {
        content = content.replace("$name", name.getText());
        content = content.replace("$packagename", packagebase + "." + packageName.getText() + ".view");
        content = content.replace("$packagebase", packagebase + "." + packageName.getText());
        content = content.replace("$applicationId", applicationId);
        content = content.replace("$layoutname", layoutName);
        return content;
    }

    /**
     * 处理fragment
     *
     * @param content
     * @return
     */
    private String dealFragment(String content) {
        content = content.replace("$name", name.getText());
        content = content.replace("$packagename", packagebase + "." + packageName.getText() + ".view");
        content = content.replace("$packagebase", packagebase + "." + packageName.getText());
        content = content.replace("$applicationId", applicationId);
        content = content.replace("$layoutname", layoutName);
        return content;
    }

    /**
     * 处理Model
     *
     * @param content
     * @return
     */
    private String dealModel(String content) {
        content = content.replace("$name", name.getText());
        content = content.replace("$packagename", packagebase + "." + packageName.getText() + ".model");
        content = content.replace("$packagebase", packagebase + "." + packageName.getText());
        return content;
    }

    /**
     * 1.通用流程,处理顶部注释
     *
     * @param content
     */
    private String dealFileTitle(String content) {
        content = content.replace("$author", username.getText());
        content = content.replace("$date", DateUtil.getNowDateShort());
        content = content.replace("$description", description.getText());
        return content;
    }

    /**
     * 读取文件--优先读取远端模板文件
     *
     * @param fileUrl
     * @param filename
     * @return
     */
    private String ReadFile(String fileUrl, String filename) {
        String result = HttpUtil.readRemoteFile(fileUrl);
        if (result == null) {
            InputStream in = null;
            in = this.getClass().getResourceAsStream("../Template/" + filename);
            String content = "";
            try {
                content = new String(FileUtils.readStream(in), "utf-8");
            } catch (Exception e) {
            }
            return content;
        } else {
            return result;
        }
    }

    /**
     * 检查待生成的文件是否存在
     */
    private CheckFileExistResult checkFileExit() {
        contractPath = rightClickPath + packageName.getText() + "/contract";
        viewPath = rightClickPath + packageName.getText() + "/view";
        presenterPath = rightClickPath + packageName.getText() + "/presenter";
        modelPath = rightClickPath + packageName.getText() + "/model";
        int begin = rightClickPath.indexOf("/src/main/java");
        layoutPath = rightClickPath.substring(0, begin) + "/src/main/res/layout";
        contractName = name.getText() + "Contract.kt";
        if (activityJB.isSelected()) {
            viewName = name.getText() + "Activity.kt";
            layoutName = "activity_" + StringUtil.upperCharToUnderLine(name.getText());
        }
        if (fragmentJB.isSelected()) {
            viewName = name.getText() + "Fragment.kt";
            layoutName = "fragment_" + StringUtil.upperCharToUnderLine(name.getText());
        }
        presenterName = name.getText() + "Presenter.kt";
        modelName = name.getText() + "Model.kt";
        if (new File(contractPath, contractName).exists())
            return new CheckFileExistResult(true, String.format("%s目录下已存在文件%s", contractPath, contractName));
        if (new File(viewPath, viewName).exists())
            return new CheckFileExistResult(true, String.format("%s目录下已存在文件%s", viewPath, viewName));
        if (new File(presenterPath, presenterName).exists())
            return new CheckFileExistResult(true, String.format("%s目录下已存在文件%s", presenterPath, presenterPath));
        if (new File(modelPath, modelName).exists())
            return new CheckFileExistResult(true, String.format("%s目录下已存在文件%s", modelPath, modelName));
        if (new File(layoutPath, layoutName + ".xml").exists())
            return new CheckFileExistResult(true, String.format("%s目录下已存在文件%s", layoutPath, layoutName + ".xml"));
        return new CheckFileExistResult(false, "OK");
    }


    public class CheckFileExistResult {
        private boolean exist;
        private String msg;

        public CheckFileExistResult(boolean exist, String msg) {
            this.exist = exist;
            this.msg = msg;
        }

        public boolean isExist() {
            return exist;
        }

        public void setExist(boolean exist) {
            this.exist = exist;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
}
